package utils

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

type CTCPSocketData struct {
	m_wBufferSize  uint16                  //数据长度
	m_cbDataBuffer [SOCKET_TCP_BUFFER]byte //数据缓存
	m_CallLog      CallbackUserLog
}

func MarkNewCTCPSocketData(CallLog CallbackUserLog) *CTCPSocketData {
	this := &CTCPSocketData{
		m_wBufferSize: 0,
		m_CallLog:     CallLog,
	}
	for i := 0; i < SOCKET_TCP_BUFFER; i++ {
		this.m_cbDataBuffer[i] = 0
	}
	return this
}

//设置数据 SOCKET_TCP_BUFFER * 8
func (this *CTCPSocketData) SetBufferData(pcbBuffer []byte, wBufferSize uint16, TCPData *tagTCPData, key string) bool {
	//如果数据缓冲小于数据大小
	if wBufferSize <= tcpinfoSize || (wBufferSize > uint16(SOCKET_TCP_BUFFER)) {
		return false
	}
	//设置数据
	//设置this.m_wBufferSize等于定义的数据的大小
	this.m_wBufferSize = wBufferSize
	copy(this.m_cbDataBuffer[0:], pcbBuffer[:wBufferSize])

	var pInfo TCP_Info
	buf := bytes.NewReader(this.m_cbDataBuffer[:wBufferSize])
	if err := binary.Read(buf, binary.LittleEndian, &pInfo); err != nil {
		if this.m_CallLog!=nil{
		this.m_CallLog(key, fmt.Sprintf("msg binary write TCP_Info error: %s", err.Error()))
		}
		return false
	}

	if pInfo.WPacketSize != wBufferSize && this.m_CallLog!=nil {
		this.m_CallLog(key, fmt.Sprintf("pInfo.wPacketSize :%d != wBufferSize : %d", pInfo.WPacketSize, wBufferSize))
		return false
	}
	// }
	//映射数据
	if this.UnMappedBuffer(key) == false  && this.m_CallLog!=nil{
		this.m_CallLog(key, fmt.Sprintf("UnMappedBuffer() failed"))
		return false
	}
	//变量定义
	var pHead TCP_Head
	buf = bytes.NewReader(this.m_cbDataBuffer[:])
	binary.Read(buf, binary.LittleEndian, &pHead)
	//设置数据
	TCPData.Command = pHead.CommandInfo
	TCPData.WDataSize = this.m_wBufferSize - TcpheadSize
	copy(TCPData.PDataBuffer[:], this.m_cbDataBuffer[TcpheadSize:])
	return true
}

//设置数据
func (this *CTCPSocketData) InitSocketData_Head(clinethead TCP_Head) bool {
	//申请一个tc发包的结构体(头部和数据)
	var pHead TCP_Head
	buf := bytes.NewReader(this.m_cbDataBuffer[:])
	//从this.m_cbDataBuffer复制给pHead
	binary.Read(buf, binary.LittleEndian, &pHead)
	//this.m_CallLog(fmt.Sprintf("读取到的TCP_Head %+v\n", pHead))

	var wDataSize uint16 = 0
	pHead.TCPInfo.CbDataKind = 0
	pHead.TCPInfo.CbCheckCode = 0
	pHead.TCPInfo.WPacketSize = TcpheadSize + wDataSize
	//设置数据长度等于包的头部和数据的大小
	this.m_wBufferSize = TcpheadSize

	//主从命令写入buf
	buf_w := new(bytes.Buffer)
	binary.Write(buf_w, binary.LittleEndian, pHead)
	copy(this.m_cbDataBuffer[:TcpheadSize], buf_w.Bytes())

	//加密数据
	var cbCheckCode byte = 0
	//tcpinfoSize包含包头和数据的大小
	for i := tcpinfoSize; i < this.m_wBufferSize; i++ {
		cbCheckCode = cbCheckCode + this.m_cbDataBuffer[i]
		this.m_cbDataBuffer[i] = g_SendByteMap[this.m_cbDataBuffer[i]]
	}

	//设置包头
	pHead.TCPInfo.CbDataKind |= DK_MAPPED
	pHead.TCPInfo.CbCheckCode = ^cbCheckCode + 1

	//封包结束 写入buf
	buf_w = new(bytes.Buffer)
	binary.Write(buf_w, binary.LittleEndian, pHead)
	copy(this.m_cbDataBuffer[:tcpinfoSize], buf_w.Bytes())

	return true
}

//设置数据(对发送的数据进行处理)
func (this *CTCPSocketData) InitSocketData(wMainCmdID uint16, wSubCmdID uint16, pData []byte, wDataSize uint16, CmdNo uint32, key string) bool {
	if int(wDataSize) > SOCKET_TCP_BUFFER && this.m_CallLog!=nil{
		this.m_CallLog(key, fmt.Sprintf("wDataSize: %d ,SOCKET_TCP_BUFFER: %d", int(wDataSize), int(SOCKET_TCP_BUFFER)))
		return false
	}
	var pHead TCP_Head
	buf := bytes.NewReader(this.m_cbDataBuffer[:])
	binary.Read(buf, binary.LittleEndian, &pHead)

	pHead.CommandInfo.WMainCmdID = wMainCmdID
	pHead.CommandInfo.WSubCmdID = wSubCmdID

	pHead.TCPInfo.CbDataKind = 0
	pHead.TCPInfo.CbCheckCode = 0
	pHead.TCPInfo.DwMessageId = CmdNo
	pHead.TCPInfo.WPacketSize = TcpheadSize + wDataSize

	if wDataSize > 0 {
		this.m_wBufferSize = TcpheadSize + wDataSize
		//	fmt.Printf("wDataSize:%d,pData大小:%d,this.m_cbDataBuffer大小%d,TcpheadSize%d\n", wDataSize, len(pData), len(this.m_cbDataBuffer), TcpheadSize)
		copy(this.m_cbDataBuffer[TcpheadSize:], pData[:wDataSize])
	} else {
		//直接设置数据长度等于tcp头部的长度和数据的长度
		this.m_wBufferSize = TcpheadSize
		//fmt.Printf("this.m_wBufferSize %d\n", this.m_wBufferSize)
	}

	//主从命令写入buf
	buf_w := new(bytes.Buffer)
	//将pHead写入buf_w
	binary.Write(buf_w, binary.LittleEndian, pHead)
	//直接设置this.m_cbDataBuffer数据长度等于tcp头部的长度和数据的长度
	copy(this.m_cbDataBuffer[:TcpheadSize], buf_w.Bytes())

	//加密数据
	var cbCheckCode byte = 0
	//fmt.Printf("tcpinfoSize %d, this.m_wBufferSize %d\n", tcpinfoSize, this.m_wBufferSize)
	for i := tcpinfoSize; i < this.m_wBufferSize; i++ {
		cbCheckCode = cbCheckCode + this.m_cbDataBuffer[i]
		this.m_cbDataBuffer[i] = g_SendByteMap[this.m_cbDataBuffer[i]]
	}

	//设置包头
	pHead.TCPInfo.CbDataKind |= DK_MAPPED
	pHead.TCPInfo.CbCheckCode = ^cbCheckCode + 1
	//封包结束 写入buf
	buf_w = new(bytes.Buffer)
	binary.Write(buf_w, binary.LittleEndian, pHead)
	copy(this.m_cbDataBuffer[:tcpinfoSize], buf_w.Bytes())
	return true
}

//映射数据
func (this *CTCPSocketData) UnMappedBuffer(key string) bool {
	if this.m_wBufferSize < TcpheadSize {
		return false
	}

	var pHead TCP_Head
	buf := bytes.NewReader(this.m_cbDataBuffer[:])
	binary.Read(buf, binary.LittleEndian, &pHead)

	if pHead.TCPInfo.WPacketSize != this.m_wBufferSize  && this.m_CallLog!=nil{
		this.m_CallLog(key, fmt.Sprintf("pHead.TCPInfo.WPacketSize:%d != this.m_wBufferSize : %d", pHead.TCPInfo.WPacketSize, this.m_wBufferSize))
		return false
	}

	var pInfo TCP_Info
	buf = bytes.NewReader(this.m_cbDataBuffer[:])
	binary.Read(buf, binary.LittleEndian, &pInfo)

	//映射数据
	if (pInfo.CbDataKind & DK_MAPPED) != 0 {
		//变量定义
		cbCheckCode := pInfo.CbCheckCode

		for i := tcpinfoSize; i < this.m_wBufferSize; i++ {
			cbCheckCode += g_RecvByteMap[this.m_cbDataBuffer[i]]
			this.m_cbDataBuffer[i] = g_RecvByteMap[this.m_cbDataBuffer[i]]
		}

		if cbCheckCode != 0  && this.m_CallLog!=nil{
			this.m_CallLog(key, "cbCheckCode!=0")
			return false
		}
	} else if this.m_CallLog!=nil {
		this.m_CallLog(key, "pInfo.CbDataKind & DK_MAPPED!=0")
	}

	return true
}
